Use libudev to find serial devices dynamically on Linux
authorOlivier Trichet <olivier@trichet.fr>
Wed, 23 Mar 2016 01:23:56 +0000 (02:23 +0100)
committerOlivier Trichet <olivier@trichet.fr>
Thu, 31 Mar 2016 17:44:21 +0000 (19:44 +0200)
gui/app.pro
gui/serial_unix.cc

index be158398ccaa8b2508352e88c52349e3e9f8010e..930cfe0f704f64f99adc7ab234fbb0d4e315836b 100755 (executable)
@@ -28,6 +28,13 @@ unix:OBJECTS_DIR = objects
 unix:RCC_DIR = objects
 
 mac:LIBS += -framework IOKit -framework CoreFoundation
+unix {
+    CONFIG += link_pkgconfig
+    packagesExist(libudev) {
+        DEFINES += HAVE_UDEV
+        PKGCONFIG += libudev
+    }
+}
 
 UI_DIR = tmp
 
index 6c65bd0e0afb773414a049d0a046c400c88e1824..f2995be467cdbbe5eb75123229742993c3b37ed7 100644 (file)
 #include "mainwindow.h"
 #if !defined (Q_OS_MAC) // FIXME: find a better way to hide this on Mac.
 
+#ifdef HAVE_UDEV
+#include <libudev.h>
+#include <QDebug>
+
+static QStringList dynamicDevices()
+{
+    struct udev *udev = udev_new();
+    if(!udev) {
+        qDebug() << "Can't create udev";
+        return QStringList();
+    }
+
+    QSet<QString> devices;
+
+    struct udev_enumerate *enumerate = udev_enumerate_new(udev);
+    udev_enumerate_add_match_subsystem(enumerate, "tty");
+    udev_enumerate_scan_devices(enumerate);
+
+    struct udev_list_entry *device;
+    udev_list_entry_foreach(device, udev_enumerate_get_list_entry(enumerate)) {
+        const char *path = udev_list_entry_get_name(device);
+        struct udev_device *dev = udev_device_new_from_syspath(udev, path);
+
+        bool okMaj, okMin;
+        int major = QString(udev_device_get_property_value(dev, "MAJOR")).toInt(&okMaj);
+        int minor = QString(udev_device_get_property_value(dev, "MINOR")).toInt(&okMin);
+        if(!okMaj || !okMin) {
+             major = -1;
+             minor = -1;
+        }
+
+        // see Documentation/devices.txt in the linux tree
+        if( !( (major == 4 || major == 5) && 0 <= minor && minor <= 63 ) ) {
+            devices << QString::fromUtf8(udev_device_get_devnode(dev));
+            /*
+            udev_device_get_sysattr_list_entry(dev);
+            udev_device_get_tags_list_entry(dev);
+            struct udev_list_entry *prop;
+            qDebug() << "Device Node Path:" << udev_device_get_devnode(dev) << path;
+            udev_list_entry_foreach(prop, udev_device_get_properties_list_entry(dev)) {
+                qDebug() << "  " << udev_list_entry_get_name(prop)
+                         << "=>" << udev_list_entry_get_value(prop);
+            }
+            */
+        }
+        udev_device_unref(dev);
+    }
+    udev_enumerate_unref(enumerate);
+    udev_unref(udev);
+
+    QStringList list = devices.toList();
+    qSort(list);
+    return list;
+}
+#else
+static QStringList dynamicDevices()
+{
+    return QStringList();
+}
+#endif
+
+
 static const char *deviceNames[] = {
   "/dev/ttyS0",
   "/dev/ttyS1",
@@ -33,8 +95,14 @@ static const char *deviceNames[] = {
 
 void MainWindow::osLoadDeviceNameCombos(QComboBox *box)
 {
+  const QStringList devices = dynamicDevices();
+  box->addItems(devices);
+
   for (int i=0; deviceNames[i]; i++) {
-    box->addItem(deviceNames[i]);
+    if(!devices.contains(deviceNames[i])) {
+      box->addItem(deviceNames[i]);
+    }
   }
 }
+
 #endif